﻿using StableDiffusionTools.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;

namespace TaggingToolkit.Framework
{
    public class DataTags : IHighlightItem
    {
        public DataTags(string fileName, string root, string imgPath = null, bool create = false)
        {
            if (create)
            {
                ChangedTagData = true;
            }
            else
            {
                TagData = File.ReadAllText(fileName);
            }
            FullPath = fileName;
            FileName = Path.GetFileName(fileName);
            RelativePath = !string.IsNullOrEmpty(root) ? FullPath.Substring(root.Length + 1) : null;

            imagePath = !string.IsNullOrEmpty(imgPath) ? imgPath : null;
        }

        public string FileName { get; private set; }
        public string FullPath { get; private set; }
        public string RelativePath { get; private set; }
        public string TagData { get; private set; } = "";
        public bool ChangedTagData { get; private set; }
        public bool ChangedCrop { get => !CropRectangle.IsEmpty; }
        public bool ChangedFinalSize{ get => !FinalSize.IsEmpty; }
        public bool ScheduledForInterrogation { get; set; } = false;
        public bool HighlightEnabled => ChangedTagData || ChangedCrop || ScheduledForInterrogation;
        public Rectangle CropRectangle { get; set; } = default(Rectangle);
        public Size FinalSize { get; set; } = default(Size);

        public Color HighlightColor
        {
            get
            {
                if (ScheduledForInterrogation)
                    return Color.Purple;
                if(ChangedTagData || ChangedCrop)
                    return Color.DarkRed;

                return Color.Magenta;
            }
        }

        private string imagePath = null;
        public string ImagePath
        {
            get
            {
                if (imagePath == null)
                {
                    imagePath = FindImagePathOrEmpty();
                }
                return imagePath;
            }
        }

        public bool SetTagData(string text)
        {
            bool dirty = false;

            if (text.Length > 32000)
                text = text.Substring(0, 32000);

            if (!TagDataMatches(text))
            {
                dirty = ChangedTagData = true;
                TagData = text;
            }

            return dirty;
        }

        public bool SaveTagData()
        {
            bool result = ChangedTagData;

            if (ChangedTagData)
            {
                ChangedTagData = false;

                File.WriteAllText(FullPath, TagData);
            }

            return result;
        }

        public bool Crop()
        {
            bool result = ChangedCrop;

            if (ChangedCrop)
            {
                //Save cropped image;
                System.Threading.Thread.Sleep(250);
                CropRectangle = Rectangle.Empty;
            }

            return result;
        }

        public bool TagDataMatches(DataTags tags)
        {
            return TagDataMatches(tags.TagData);
        }

        public bool TagDataMatches(string other)
        {
            return TagData.Length == other.Length && string.CompareOrdinal(TagData, other) == 0;
        }

        public bool ApplyActions(string[] remove = null, string[] addFront = null, string[] addBack = null, string[][] rename = null)
        {
            bool result = false;

            bool wasRenamedOrRemoved = false;
            bool hasFrontStr = addFront.Length > 0;
            bool hasBackStr = addBack.Length > 0;
            bool hasRemove = remove.Length > 0;
            bool hasRename = rename.Length > 0;

            string addFrontStr = string.Join(", ", addFront);
            string addBackStr = string.Join(", ", addBack);
            List<string> splitTagData = null;
            StringBuilder sb = new StringBuilder(TagData.Length + addFrontStr.Length + addBackStr.Length);

            if (hasRemove || hasRename || hasFrontStr || hasBackStr)
            {
                string[] splitComma = TagData.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                splitTagData = new List<string>(splitComma);
                for (int i = splitTagData.Count - 1; i >= 0; i--)
                {
                    string trimmed = splitTagData[i] = splitTagData[i].Trim();

                    bool wasRemoved = false;
                    for (int j = 0; j < remove.Length; j++)
                    {
                        if (trimmed == remove[j])
                        {
                            wasRenamedOrRemoved = wasRemoved = true;
                            splitTagData.RemoveAt(i);
                            break;
                        }
                    }

                    if (!wasRemoved)
                    {
                        for (int j = 0; j < rename.Length; j++)
                        {
                            if (trimmed == rename[j][0])
                            {
                                wasRenamedOrRemoved = true;
                                splitTagData[i] = rename[j][1];
                                break;
                            }
                        }
                    }

                    if (!wasRenamedOrRemoved)
                    {
                        for (int j = 0; j < addFront.Length; j++)
                        {
                            if (trimmed == addFront[j])
                            {
                                wasRenamedOrRemoved = true;
                                splitTagData.RemoveAt(i);
                                break;
                            }
                        }
                        for (int j = 0; j < addBack.Length; j++)
                        {
                            if (trimmed == addBack[j])
                            {
                                wasRenamedOrRemoved = true;
                                splitTagData.RemoveAt(i);
                                break;
                            }
                        }
                    }
                }
            }

            if (hasFrontStr)
                sb.Append(addFrontStr + ", ");

            if (wasRenamedOrRemoved)
            {
                result = ChangedTagData = true;
                sb.Append(string.Join(", ", splitTagData));
            }
            else if (hasFrontStr || hasBackStr)
            {
                result = ChangedTagData = true;
                sb.Append(TagData);
            }

            if (hasBackStr)
                sb.Append(", " + addBackStr);


            if (result)
                TagData = sb.ToString();


            return result;
        }

        private string FindImagePathOrEmpty()
        {
            string imageName = Path.GetFileNameWithoutExtension(FullPath);
            string rootPath = Directory.GetParent(FullPath).FullName;
            for (int i = 0; i < ImageUtil.CommonImageExtensions.Count; i++)
            {
                string tryImagePath = Path.Combine(rootPath, $"{imageName}{ImageUtil.CommonImageExtensions[i]}");
                if (ExtendedPathInfo.GetPathInfo(tryImagePath) == PathInfo.File)
                {
                    return tryImagePath;
                }
            }

            return "";
        }
    }
}
